<?php

Raise::load('core.RaiseHelper');
Raise::load('core.RaiseVariable');
Raise::load('core.IpAddress');

/**
 * RaiseHttpClient class
 * Represents the client on the other end of the HTTP connection
 *
 * @author Sam-Mauris Yong <hellclanner at live dot com>
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package Raise.Core.HTTP
 * @since 1.2
 */
class RaiseHttpClient extends RaiseHelper {

    /**
     * Operating System: Microsoft Windows
     */
    const OS_WINDOWS = 'Windows';

    /**
     * Operating System: Apple Macintosh
     */
    const OS_MAC = 'Mac';

    /**
     * Operating System: Linux
     */
    const OS_LINUX = 'Linux';

    /**
     * Operating System: UNIX
     */
    const OS_UNIX = 'UNIX';

    /**
     * Operating System: Unknown
     */
    const OS_UNKNOWN = '';

    /**
     * Browser: Mozilla Firefox
     */
    const BR_FIREFOX = 'Firefox';

    /**
     * Browser: Windows Internet Explorer
     */
    const BR_IE = 'IE';

    /**
     * Browser: Apple Safari
     */
    const BR_SAFARI = 'Safari';

    /**
     * Browser: Opera
     */
    const BR_OPERA = 'Opera';

    /**
     * Browser: Unknown
     */
    const BR_UNKNOWN = '';

    /**
     * The browser name of the client
     * @var string
     */
    private $browserName;

    /**
     * The version of the browser the client is using
     * @var string
     */
    private $browserVersion;

    /**
     * The Operating System of the client
     * @var string
     */
    private $operatingSystem;

    /**
     * Flag whether or not this client is a bot
     * @var boolean
     */
    private $bot = false;

    /**
     * The user agent string of this RaiseHttpClient
     * @var string
     */
    private $userAgent;

    /**
     * The remote IpAddress of this RaiseHttpClient
     * @var IpAddress
     */
    private $ipAddress;

    /**
     * Caching for RaiseHttpClient of the current HTTP request
     * @var RaiseHttpClient
     */
    private static $current;

    /**
     * Create a RaiseHttpClient object based on the IpAddress and UserAgent
     * @param IpAddress $ip The IP Address of the client
     * @param string $userAgent The user agent string to parse
     */
    public function __construct($ip, $userAgent){

        if(!RaiseVariable::isA($ip, 'IpAddress')){
            $ip = new IpAddress($ip);
        }
        $this->ipAddress = $ip;

        $this->userAgent = $userAgent;

        if(preg_match( '|Opera/([0-9].[0-9]{1,2})|', $this->userAgent(), $matched)){
            $browser_version = $matched[1];
            $browser = self::BR_OPERA;
        }elseif(preg_match('|MSIE ([0-9].[0-9]{1,2})|', $this->userAgent(), $matched)){
            $browser_version = $matched[1];
            $browser = self::BR_IE;
        }elseif(preg_match('|Firefox/([0-9\.]+)|', $this->userAgent(), $matched)){
                $browser_version = $matched[1];
                $browser = self::BR_FIREFOX;
        }elseif(preg_match('|Safari/([0-9\.]+)|', $this->userAgent(), $matched)){
                $browser_version = $matched[1];
                $browser = self::BR_SAFARI;
        }else{
            // browser not recognized!
            $browser_version = '';
            $browser = self::BR_UNKNOWN;
        }
        
        $this->browserName = $browser;
        $this->browserVersion = $browser_version;
        if (strstr($this->userAgent(), 'Win')) {
            $this->operatingSystem = self::OS_WINDOWS;
        } else if (strstr($this->userAgent(),'Mac')) {
            $this->operatingSystem = self::OS_MAC;
        } else if (strstr($this->userAgent(), 'Linux')) {
            $this->operatingSystem = self::OS_LINUX;
        } else if (strstr($this->userAgent(), 'Unix')) {
            $this->operatingSystem = self::OS_UNIX;
        } else {
            $this->operatingSystem = self::OS_UNKNOWN;;
        }

        // A list of known robots
        $bot_array = array('jeevesteoma', 'msnbot', 'slurp', 'jeevestemoa', 'gulper', 'googlebot', 'linkwalker', 'validator', 'webaltbot', 'wget', 'bot');
        
        //replace all but alphabets
        $ua = strtolower(preg_replace('/[^a-zA-Z _]*/', '', $this->userAgent()));
        //check for intersections
        $this->bot = (bool)count(array_intersect(explode(' ', $ua), $bot_array));
    }

    /**
     * Get the browser name of this RaiseHttpClient
     * @return string
     */
    public function browserName(){
        return $this->browserName;
    }


    /**
     * Get the browser version of this RaiseHttpClient
     * @return string
     */
    public function browserVersion(){
        return $this->browserVersion;
    }


    /**
     * Get the operating system of this RaiseHttpClient
     * @return string
     */
    public function operatingSystem(){
        return $this->operatingSystem;
    }

    /**
     * Get the User Agent string of this RaiseHttpClient
     * @return string
     */
    public function userAgent(){
        return $this->userAgent;
    }

    /**
     * Get the remote IpAddress of this RaiseHttpClient
     * @return IpAddress
     */
    public function ipAddress(){
        return $this->ipAddress;
    }

    /**
     * Query whether this RaiseHttpClient is bot or not
     * @return boolean
     */
    public function bot(){
        return $this->bot;
    }

    /**
     * Load the RaiseHttpClient based on current request
     * @return RaiseHttpClient
     * @static
     */
    public static function loadCurrent(){
        if(!self::$current){
            self::$current = new self($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT']);
        }
        return self::$current;
    }
}